package test

import (
	"aigen-todo/internal/service"
	"aigen-todo/internal/models"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/mock"
)

// MockTaskRepository 是TaskRepository的模拟实现
type MockTaskRepository struct {
	mock.Mock
}

func (m *MockTaskRepository) Create(task *models.Task) error {
	args := m.Called(task)
	return args.Error(0)
}

func (m *MockTaskRepository) GetByID(id uint64) (*models.Task, error) {
	args := m.Called(id)
	if args.Get(0) == nil {
		return nil, args.Error(1)
	}
	return args.Get(0).(*models.Task), args.Error(1)
}

func (m *MockTaskRepository) GetByUserID(userID uint64) ([]models.Task, error) {
	args := m.Called(userID)
	if args.Get(0) == nil {
		return nil, args.Error(1)
	}
	return args.Get(0).([]models.Task), args.Error(1)
}

func (m *MockTaskRepository) GetByGroupID(groupID uint64) ([]models.Task, error) {
	args := m.Called(groupID)
	if args.Get(0) == nil {
		return nil, args.Error(1)
	}
	return args.Get(0).([]models.Task), args.Error(1)
}

func (m *MockTaskRepository) GetMyDayTasks(userID uint64) ([]models.Task, error) {
	args := m.Called(userID)
	if args.Get(0) == nil {
		return nil, args.Error(1)
	}
	return args.Get(0).([]models.Task), args.Error(1)
}

func (m *MockTaskRepository) Update(task *models.Task) error {
	args := m.Called(task)
	return args.Error(0)
}

func (m *MockTaskRepository) Delete(id uint64) error {
	args := m.Called(id)
	return args.Error(0)
}

func (m *MockTaskRepository) ChangeGroup(taskID, groupID uint64) error {
	args := m.Called(taskID, groupID)
	return args.Error(0)
}

// MockTaskGroupRepository 是TaskGroupRepository的模拟实现
type MockTaskGroupRepository struct {
	mock.Mock
}

func (m *MockTaskGroupRepository) Create(group *models.TaskGroup) error {
	args := m.Called(group)
	return args.Error(0)
}

func (m *MockTaskGroupRepository) GetByID(id uint64) (*models.TaskGroup, error) {
	args := m.Called(id)
	if args.Get(0) == nil {
		return nil, args.Error(1)
	}
	return args.Get(0).(*models.TaskGroup), args.Error(1)
}

func (m *MockTaskGroupRepository) GetByUserID(userID uint64) ([]models.TaskGroup, error) {
	args := m.Called(userID)
	if args.Get(0) == nil {
		return nil, args.Error(1)
	}
	return args.Get(0).([]models.TaskGroup), args.Error(1)
}

func (m *MockTaskGroupRepository) GetDefaultGroupByUserID(userID uint64) (*models.TaskGroup, error) {
	args := m.Called(userID)
	if args.Get(0) == nil {
		return nil, args.Error(1)
	}
	return args.Get(0).(*models.TaskGroup), args.Error(1)
}

func (m *MockTaskGroupRepository) Update(group *models.TaskGroup) error {
	args := m.Called(group)
	return args.Error(0)
}

func (m *MockTaskGroupRepository) Delete(id uint64) error {
	args := m.Called(id)
	return args.Error(0)
}

// TestTaskService_CreateTask 测试创建任务功能
func TestTaskService_CreateTask(t *testing.T) {
	// 创建模拟仓库
	mockTaskRepo := new(MockTaskRepository)
	mockTaskGroupRepo := new(MockTaskGroupRepository)
	mockUserRepo := new(MockUserRepository)
	taskService := service.NewTaskService(mockTaskRepo, mockTaskGroupRepo, mockUserRepo)

	// 测试用例1：创建任务成功
	t.Run("CreateTaskSuccess", func(t *testing.T) {
		// 设置模拟返回值
		userID := uint64(1)
		groupID := uint64(1)
		title := "测试任务"
		description := "测试任务描述"
		isImportant := false
		isMyDay := false
		dueDate := time.Now()

		// 模拟用户存在
		mockUserRepo.On("GetByID", userID).Return(&models.User{
			ID:       userID,
			Username: "testuser",
			Email:    "test@example.com",
		}, nil)

		// 模拟任务分组存在
		mockTaskGroupRepo.On("GetByID", groupID).Return(&models.TaskGroup{
			ID:     groupID,
			UserID: userID,
			Name:   "默认分组",
		}, nil)

		// 模拟创建任务
		mockTaskRepo.On("Create", mock.AnythingOfType("*models.Task")).Return(nil)

		// 执行测试
		task, err := taskService.CreateTask(userID, groupID, title, description, isImportant, isMyDay, &dueDate)

		// 验证结果
		assert.NoError(t, err)
		assert.NotNil(t, task)
		assert.Equal(t, title, task.Title)
		assert.Equal(t, description, task.Description)
		assert.Equal(t, isImportant, task.IsImportant)
		assert.Equal(t, isMyDay, task.IsMyDay)
		mockTaskRepo.AssertExpectations(t)
		mockTaskGroupRepo.AssertExpectations(t)
	})

	// 测试用例2：创建任务失败 - 任务分组不存在
	t.Run("CreateTaskGroupNotFound", func(t *testing.T) {
		// 设置模拟返回值
		userID := uint64(1)
		groupID := uint64(999) // 不存在的分组ID
		title := "测试任务"
		description := "测试任务描述"
		isImportant := false
		isMyDay := false
		dueDate := time.Now()

		// 模拟任务分组不存在
		mockTaskGroupRepo.On("GetByID", groupID).Return(nil, service.ErrTaskGroupNotFound)

		// 执行测试
		task, err := taskService.CreateTask(userID, groupID, title, description, isImportant, isMyDay, &dueDate)

		// 验证结果
		assert.Error(t, err)
		assert.Nil(t, task)
		assert.Equal(t, service.ErrTaskGroupNotFound, err)
		mockTaskGroupRepo.AssertExpectations(t)
	})
}

// TestTaskService_GetTasksByUserID 测试获取用户任务列表功能
func TestTaskService_GetTasksByUserID(t *testing.T) {
	// 创建模拟仓库
	mockTaskRepo := new(MockTaskRepository)
	mockTaskGroupRepo := new(MockTaskGroupRepository)
	mockUserRepo := new(MockUserRepository)
	taskService := service.NewTaskService(mockTaskRepo, mockTaskGroupRepo, mockUserRepo)

	// 测试用例：获取用户任务列表成功
	userID := uint64(1)
	expectedTasks := []models.Task{
		{
			ID:          1,
			UserID:      userID,
			GroupID:     1,
			Title:       "任务1",
			Description: "任务1描述",
			IsImportant: false,
			IsMyDay:     false,
			Status:      models.StatusNew,
			CreatedAt:   time.Now(),
		},
		{
			ID:          2,
			UserID:      userID,
			GroupID:     1,
			Title:       "任务2",
			Description: "任务2描述",
			IsImportant: true,
			IsMyDay:     true,
			Status:      models.StatusInProgress,
			CreatedAt:   time.Now(),
		},
	}

	// 设置模拟返回值
	mockTaskRepo.On("GetByUserID", userID).Return(expectedTasks, nil)

	// 执行测试
	tasks, err := taskService.GetTasksByUserID(userID)

	// 验证结果
	assert.NoError(t, err)
	assert.NotNil(t, tasks)
	assert.Len(t, tasks, 2)
	assert.Equal(t, expectedTasks[0].Title, tasks[0].Title)
	assert.Equal(t, expectedTasks[1].Title, tasks[1].Title)
	mockTaskRepo.AssertExpectations(t)
}

// TestTaskService_GetTaskByID 测试通过ID获取任务功能
func TestTaskService_GetTaskByID(t *testing.T) {
	// 创建模拟仓库
	mockTaskRepo := new(MockTaskRepository)
	mockTaskGroupRepo := new(MockTaskGroupRepository)
	mockUserRepo := new(MockUserRepository)
	taskService := service.NewTaskService(mockTaskRepo, mockTaskGroupRepo, mockUserRepo)

	// 测试用例1：获取任务成功
	t.Run("GetTaskByIDSuccess", func(t *testing.T) {
		// 设置模拟返回值
		taskID := uint64(1)
		expectedTask := &models.Task{
			ID:          taskID,
			UserID:      1,
			GroupID:     1,
			Title:       "测试任务",
			Description: "测试任务描述",
			IsImportant: false,
			IsMyDay:     false,
			Status:      models.StatusNew,
			CreatedAt:   time.Now(),
		}
		mockTaskRepo.On("GetByID", taskID).Return(expectedTask, nil)

		// 执行测试
		task, err := taskService.GetTaskByID(taskID)

		// 验证结果
		assert.NoError(t, err)
		assert.NotNil(t, task)
		assert.Equal(t, taskID, task.ID)
		mockTaskRepo.AssertExpectations(t)
	})

	// 测试用例2：获取任务失败 - 任务不存在
	t.Run("GetTaskByIDNotFound", func(t *testing.T) {
		// 设置模拟返回值
		taskID := uint64(999) // 不存在的任务ID
		mockTaskRepo.On("GetByID", taskID).Return(nil, service.ErrTaskNotFound)

		// 执行测试
		task, err := taskService.GetTaskByID(taskID)

		// 验证结果
		assert.Error(t, err)
		assert.Nil(t, task)
		assert.Equal(t, service.ErrTaskNotFound, err)
		mockTaskRepo.AssertExpectations(t)
	})
}

// TestTaskService_UpdateTask 测试更新任务功能
func TestTaskService_UpdateTask(t *testing.T) {
	// 创建模拟仓库
	mockTaskRepo := new(MockTaskRepository)
	mockTaskGroupRepo := new(MockTaskGroupRepository)
	mockUserRepo := new(MockUserRepository)
	taskService := service.NewTaskService(mockTaskRepo, mockTaskGroupRepo, mockUserRepo)

	// 设置模拟返回值
	taskID := uint64(1)
	userID := uint64(1)
	groupID := uint64(1)

	// 模拟任务存在
	existingTask := &models.Task{
		ID:          taskID,
		UserID:      userID,
		GroupID:     groupID,
		Title:       "旧任务标题",
		Description: "旧任务描述",
		IsImportant: false,
		IsMyDay:     false,
		Status:      models.StatusNew,
		CreatedAt:   time.Now(),
	}
	mockTaskRepo.On("GetByID", taskID).Return(existingTask, nil)

	// 模拟更新任务
	mockTaskRepo.On("Update", mock.AnythingOfType("*models.Task")).Return(nil)

	// 执行测试：更新任务标题
	newTitle := "新任务标题"
	updatedTask := *existingTask
	updatedTask.Title = newTitle

	err := taskService.UpdateTask(&updatedTask)

	// 验证结果
	assert.NoError(t, err)
	mockTaskRepo.AssertExpectations(t)
}

// TestTaskService_DeleteTask 测试删除任务功能
func TestTaskService_DeleteTask(t *testing.T) {
	// 创建模拟仓库
	mockTaskRepo := new(MockTaskRepository)
	mockTaskGroupRepo := new(MockTaskGroupRepository)
	mockUserRepo := new(MockUserRepository)
	taskService := service.NewTaskService(mockTaskRepo, mockTaskGroupRepo, mockUserRepo)

	// 设置模拟返回值
	taskID := uint64(1)

	// 模拟删除任务
	mockTaskRepo.On("Delete", taskID).Return(nil)

	// 执行测试
	err := taskService.DeleteTask(taskID)

	// 验证结果
	assert.NoError(t, err)
	mockTaskRepo.AssertExpectations(t)
}
